import {AtpAgent} from '@atproto/api' import {type AnyProfileView} from '#/types/bsky/profile' type PResp = Awaited> // based on https://github.com/Janpot/escape-html-template-tag/blob/master/src/index.ts const ENTITIES: { [key: string]: string } = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=', } const ENT_REGEX = new RegExp(Object.keys(ENTITIES).join('|'), 'g') function escapehtml(unsafe: Sub): string { if (Array.isArray(unsafe)) { return unsafe.map(escapehtml).join('') } if (unsafe instanceof HtmlSafeString) { return unsafe.toString() } return String(unsafe).replace(ENT_REGEX, char => ENTITIES[char]) } type Sub = HtmlSafeString | string | (HtmlSafeString | string)[] export class HtmlSafeString { private _parts: readonly string[] private _subs: readonly Sub[] constructor(parts: readonly string[], subs: readonly Sub[]) { this._parts = parts this._subs = subs } toString(): string { let result = this._parts[0] for (let i = 1; i < this._parts.length; i++) { result += escapehtml(this._subs[i - 1]) + this._parts[i] } return result } } export function html(parts: TemplateStringsArray, ...subs: Sub[]) { return new HtmlSafeString(parts, subs) } export const renderHandleString = (profile: AnyProfileView) => profile.displayName ? `${profile.displayName} (@${profile.handle})` : `@${profile.handle}` class HeadHandler { profile: PResp url: string constructor(profile: PResp, url: string) { this.profile = profile this.url = url } async element(element) { const view = this.profile.data const description = view.description ? html` ` : '' const img = view.banner ? html` ` : view.avatar ? html`` : '' element.append( html` ${description} ${img} `, {html: true}, ) } } class TitleHandler { profile: PResp constructor(profile: PResp) { this.profile = profile } async element(element) { element.setInnerContent(renderHandleString(this.profile.data)) } } class NoscriptHandler { profile: PResp constructor(profile: PResp) { this.profile = profile } async element(element) { const view = this.profile.data element.append( html`

Profile

${view.displayName ?? ''}

${view.handle}

${view.did}

${view.description ?? ''}

`, {html: true}, ) } } export async function onRequest(context) { const agent = new AtpAgent({service: 'https://public.api.bsky.app/'}) const {request, env} = context const origin = new URL(request.url).origin const base = env.ASSETS.fetch(new URL('/', origin)) try { const profile = await agent.getProfile({ actor: context.params.handleOrDID, }) return new HTMLRewriter() .on(`head`, new HeadHandler(profile, request.url)) .on(`title`, new TitleHandler(profile)) .on(`noscript`, new NoscriptHandler(profile)) .transform(await base) } catch (e) { console.error(e) return await base } }